package gee

import (
	"fmt"
	"log"
	"strings"
)

type Node struct {
	//待匹配路由
	pattern string
	//路由的一部分
	part string
	//子节点
	children []*Node
	//是否属于模糊匹配的路由节点
	isWild bool
}

//查询所有能匹配到的,当层处理
func (node *Node) matchChild(part string) []*Node {
	tempSlim := make([]*Node, 0)
	nodeTemp := node.children
	for i := range nodeTemp {
		if nodeTemp[i].isWild || nodeTemp[i].part == part {
			tempSlim = append(tempSlim, nodeTemp[i])
		}
	}
	if len(tempSlim) == 0 {
		return nil
	}
	return tempSlim
}

//查找符合要求的可被插入项,当层查找
func (node *Node) findedChild(part string) *Node {
	nodeTemp := node.children
	for i := range nodeTemp {
		if nodeTemp[i].isWild || nodeTemp[i].part == part {
			return nodeTemp[i]
		}
	}
	return nil
}

//路由插入,注册函数
func (root *Node) InsertNode(parts []string, pattern string) {
	cur := root
	pre := &Node{}
	for i := 1; i != len(parts); i++ {
		pre = cur
		cur = cur.findedChild(parts[i])
		if cur == nil {
			var newNode *Node
			if i == len(parts)-1 {
				newNode = &Node{
					pattern:  pattern,
					part:     parts[i],
					children: make([]*Node, 0),
					isWild:   (strings.Contains(parts[i], ":") || strings.Contains(parts[i], "*")),
				}
			} else {
				newNode = &Node{
					part:     parts[i],
					children: make([]*Node, 0),
					isWild:   (strings.Contains(parts[i], ":") || strings.Contains(parts[i], "*")),
				}
			}
			pre.children = append(pre.children, newNode)
			cur = newNode
		}
	}
}

//查找匹配的项
func (node *Node) SearchNode(parts []string, height int) *Node {
	if len(parts) == height || strings.HasPrefix(node.part, "*") {
		if node.pattern == "" {
			return nil
		}
		return node
	}
	var result *Node
	tempNodeSlice := node.matchChild(parts[height])
	for i := range tempNodeSlice {
		result = tempNodeSlice[i].SearchNode(parts, height+1)
		if result != nil {
			break
		}
	}
	return result
}

type Router struct {
	handle map[string]HandleFunc
	root   map[string]*Node
}

func NewRouter() *Router {
	return &Router{
		handle: make(map[string]HandleFunc),
		root:   make(map[string]*Node),
	}
}

func parsePattern(pattern string) []string {
	tempStr := strings.Split(pattern, "/")

	var result []string
	for i := range tempStr {
		result = append(result, tempStr[i])
		if strings.Contains(tempStr[i], "*") {
			break
		}
	}

	return result
}

func (router *Router) addRoute(method string, pattern string, handle HandleFunc) {
	var builder strings.Builder
	builder.Grow(len(method) + len(pattern) + 5)
	builder.WriteString(method)
	builder.WriteString("-")
	builder.WriteString(pattern)
	router.handle[builder.String()] = handle

	patternParesed := parsePattern(pattern)
	node, flag := router.root[method]
	if flag {
		node.InsertNode(patternParesed, pattern)
	} else {
		router.root[method] = &Node{}
		router.root[method].InsertNode(patternParesed, pattern)
	}
}

func (rouer *Router) getRoute(method string, pattern string) (*Node, map[string]string) {
	parsedPattern := parsePattern(pattern)
	node, flag := rouer.root[method]
	param := make(map[string]string)
	if flag {
		result := node.SearchNode(parsedPattern, 1) //应该从第二个元素开始找，第一个元素是空,所以是1不是0
		if result == nil {
			log.Printf("未查找到注册路由，%s", pattern)
			return nil, nil
		}
		tempStr := parsePattern(result.pattern)
		for i := 1; i != len(tempStr); i++ {
			//不能使用tempStr[i][0] == ":"来判断，如果此项字节数为0则直接出bug
			if strings.Contains(tempStr[i], ":") {
				param[tempStr[i][1:]] = parsedPattern[i]
			}
			if strings.Contains(tempStr[i], "*") {
				param[tempStr[i][1:]] = strings.Join(parsedPattern[i:], "/")
				break //星号是匹配所有，所以后面就不用再匹配了
			}
		}
		return result, param
	} else {
		return nil, nil
	}
}

func (router *Router) handles(c *Context) {
	var builder strings.Builder
	//前缀树能找到，就一定注册了func，所以不用node
	node, param := router.getRoute(c.Method, c.Path)
	if node == nil {
		c.handles = append(c.handles, func(context *Context) {
			fmt.Fprintf(context.W, "404 not found: %s\n", context.Path)
		})
	} else {
		c.Params = param
		builder.Grow(len(c.Method) + len(node.pattern) + 5)
		builder.WriteString(c.Method)
		builder.WriteString("-")
		builder.WriteString(node.pattern)
		c.handles = append(c.handles, router.handle[builder.String()])
	} //全部放入handles中，再配合Next()以实现中间件的处理顺序
	//可以灵活的在用户注册的路由处理函数handle前中后行使，举例如下。
	c.Next()
}

// 假设我们应用了中间件 A 和 B，和路由映射的 Handler。c.handlers是这样的[A, B, Handler]，c.index初始化为-1。调用c.Next()，接下来的流程是这样的：

// c.index++，c.index 变为 0
// 0 < 3，调用 c.handlers[0]，即 A
// 执行 part1，调用 c.Next()
// c.index++，c.index 变为 1
// 1 < 3，调用 c.handlers[1]，即 B
// 执行 part3，调用 c.Next()
// c.index++，c.index 变为 2
// 2 < 3，调用 c.handlers[2]，即Handler
// Handler 调用完毕，返回到 B 中的 part4，执行 part4
// part4 执行完毕，返回到 A 中的 part2，执行 part2
// part2 执行完毕，结束。
// 一句话说清楚重点，最终的顺序是part1 -> part3 -> Handler -> part 4 -> part2。恰恰满足了我们对中间件的要求，接下来看调用部分的代码，就能全部串起来了。
